﻿/* ==============================================================================
*
*   Copyright (c) 2010, Pierre Favier
*   All rights reserved.
*
*   NTasking is free software: you can redistribute it and/or modify it
*   under the terms of the GNU General Public License as published by the
*   Free Software Foundation.
*
*   Redistribution and use in source and binary forms, with or without
*   modification, are permitted provided that the following conditions
*   are met:
*
*   -   Redistributions of source code must retain the above copyright notice,
*       this list of conditions and the following disclaimer.
*
*   -   Redistributions in binary form must reproduce the above
*       copyright notice, this list of conditions and the following
*       disclaimer in the documentation and/or other materials
*       provided with the distribution.
*
*   THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
*   WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
*   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
*   DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
*   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
*   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
*   TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
*   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
*   ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
*   TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
*   THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
*   SUCH DAMAGE.
*
* ============================================================================== */

using System;
using NTasking.Internals;

namespace NTasking
{
    // ReSharper disable InconsistentNaming

    // Contains various classes and extension methods which allow to implement the fluent syntax
    // for writing a selective accept
    //
    // The SA abreviation in interfaces and class names stands for SelectiveAccept

    /// <summary>
    /// Define extension methods which allow to implement the fluent syntax for writing a selective accept
    /// </summary>
    public static class SelectiveAcceptSyntaxEx
    {

        #region Internal Classes

        public interface ISADelay<T>
            where T : ISADelay<T>
        { }


        public interface ISARelativeDelay : ISADelay<ISARelativeDelay> { }


        public interface ITSAbsoluteDelay : ISADelay<ITSAbsoluteDelay> { }


        public interface ISAAnyDelay : ISADelay<ISAAnyDelay>, ISARelativeDelay, ITSAbsoluteDelay { }


        public interface ISAComplete { }


        public interface ISABeforeElse { }


        // ReSharper disable UnusedTypeParameter
        public interface ISABeforeThen<T>
            // ReSharper restore UnusedTypeParameter
            where T : SASyntaxBase, new() { }


        // ReSharper disable UnusedTypeParameter
        public interface ISABeforeAccept<T>
            // ReSharper restore UnusedTypeParameter
            where T : SASyntaxBase, new() { }


        // ReSharper disable UnusedTypeParameter
        public interface ISABeforeAccept<T, IndexT> : ISABeforeAccept<T>
            // ReSharper restore UnusedTypeParameter
            where T : SASyntaxBase, new() { }


        // ReSharper disable UnusedTypeParameter
        public interface ISABeforeWhen<T>
            // ReSharper restore UnusedTypeParameter
            where T : SASyntaxBase, new() { }


        // ReSharper disable UnusedTypeParameter
        public interface ISABeforeIndexedWhen<T>
            // ReSharper restore UnusedTypeParameter
            where T : SASyntaxBase, new() { }


        public class SASyntaxBase
        {
            internal SelectiveAccept Select { get; set; }
        }


        public class SABeforeOrWhenDelay<T> : SASyntaxBase
            where T : ISADelay<T>
        {
            /// <summary>
            /// Add a new alternative.
            /// </summary>
            /// <value></value>
            public SABeforeWhenDelay<T> Or { get { return new SABeforeWhenDelay<T> { Select = Select }; } }
        }


        // ReSharper disable UnusedTypeParameter
        public class SABeforeDelay<T> : SASyntaxBase, ISADelay<T>
            // ReSharper restore UnusedTypeParameter
            where T : ISADelay<T>
        {
        }


        public class SABeforeOrWhenAny : SASyntaxBase
        {
            /// <summary>
            /// Add a new alternative.
            /// </summary>
            /// <value></value>
            public SABeforeWhenAny Or { get { return new SABeforeWhenAny { Select = Select }; } }
        }



        public class SABeforeAccept<T> : SASyntaxBase, ISABeforeAccept<T>
            where T : SASyntaxBase, new() { }


        public class SABeforeWhenAccept<T> : SABeforeAccept<T>, ISABeforeWhen<SABeforeAccept<T>>
            where T : SASyntaxBase, new() { }


        // ReSharper disable UnusedTypeParameter
        public class SABeforeAccept<IndexT, T> : SASyntaxBase, ISABeforeAccept<T, IndexT>
            // ReSharper restore UnusedTypeParameter
            where T : SASyntaxBase, new() { }


        public class SABeforeAny : SABeforeAccept<SAAfterNextAccept>, ISAAnyDelay
        {
            //public TSAnyDelay Delay { get { return new TSAnyDelay(); } }

            /// <summary>
            /// Add a terminate alternative.
            /// </summary>
            /// <value></value>
            public SAAfterTerminate Terminate
            {
                get
                {
                    Select.HasTerminate = true;

                    return new SAAfterTerminate { Select = Select };
                }
            }
        }


        public class SAAfterTerminate : SASyntaxBase, ISAComplete { }


        public class SABeforeWhenAny : SABeforeAny, ISABeforeWhen<SABeforeAny>, ISABeforeIndexedWhen<SAAfterNextAccept> { }


        public class SAAfterSelect : SABeforeWhenAccept<SAAfterFirstAccept>, ISABeforeIndexedWhen<SAAfterFirstAccept> { }


        public class SAAfterFirstAcceptContinuation : SABeforeOrWhenAny, ISABeforeElse { }


        public class SAAfterFirstAccept : SAAfterFirstAcceptContinuation, ISABeforeThen<SAAfterFirstAcceptContinuation> { }


        public class SAAfterNextAcceptContinuation : SAAfterFirstAcceptContinuation, ISAComplete { }


        public class SAAfterNextAccept : SAAfterNextAcceptContinuation, ISABeforeThen<SAAfterNextAcceptContinuation> { }


        public class SABeforeWhenDelay<T> : SABeforeDelay<T>, ISABeforeWhen<SABeforeDelay<T>>
            where T : ISADelay<T> { }


        public class SAAfterDelayContinuation<T> : SABeforeOrWhenDelay<T>, ISAComplete
            where T : ISADelay<T> { }


        public class SAAfterDelay<T> : SAAfterDelayContinuation<T>, ISABeforeThen<SAAfterDelayContinuation<T>>
            where T : ISADelay<T> { }


        public class SAAfterElse : SASyntaxBase, ISAComplete { }

        #endregion


        #region Implementation of ISARelativeDelay

        /// <summary>
        /// Add a delay alternative.
        /// </summary>
        /// <param name="delay">The current instance</param>
        /// <param name="duration">The delay duration.</param>
        /// <returns></returns>
        public static SAAfterDelay<ISARelativeDelay> Delay(this ISADelay<ISARelativeDelay> delay, TimeSpan duration)
        {
            SelectiveAccept s = ((SASyntaxBase)delay).Select;

            Timeout timeout = new Timeout(duration) { Barrier = s.CurrentSimpleBarrier };

            if (timeout.IsOpened() && s.Timeout.IsLater(timeout))
                s.Timeout = timeout;

            s.CurrentContinuable = timeout;

            return new SAAfterDelay<ISARelativeDelay> { Select = s };
        }


        /// <summary>
        /// Add a delay alternative.
        /// </summary>
        /// <param name="delay">The current instance</param>
        /// <param name="milliseconds">The delay duration in milliseconds.</param>
        /// <returns></returns>
        public static SAAfterDelay<ISARelativeDelay> Delay(this ISADelay<ISARelativeDelay> delay, int milliseconds)
        {
            SelectiveAccept s = ((SASyntaxBase)delay).Select;

            Timeout timeout = new Timeout(milliseconds) { Barrier = s.CurrentSimpleBarrier };

            if (timeout.IsOpened() && s.Timeout.IsLater(timeout))
                s.Timeout = timeout;

            s.CurrentContinuable = timeout;

            return new SAAfterDelay<ISARelativeDelay> { Select = s };
        }


        /// <summary>
        /// Add a delay alternative.
        /// </summary>
        /// <param name="delay">The current instance</param>
        /// <param name="seconds">The delay duration in seconds.</param>
        /// <returns></returns>
        public static SAAfterDelay<ISARelativeDelay> Delay(this ISADelay<ISARelativeDelay> delay, double seconds)
        {
            SelectiveAccept s = ((SASyntaxBase)delay).Select;

            Timeout timeout = new Timeout(seconds) { Barrier = s.CurrentSimpleBarrier };

            if (timeout.IsOpened() && s.Timeout.IsLater(timeout))
                s.Timeout = timeout;

            s.CurrentContinuable = timeout;

            return new SAAfterDelay<ISARelativeDelay> { Select = s };
        }

        #endregion


        #region Implementation of ITSAbsoluteDelay

        /// <summary>
        /// Add a delay alternative.
        /// </summary>
        /// <param name="delay">The current instance</param>
        /// <param name="date">The delay end.</param>
        /// <returns></returns>
        public static SAAfterDelay<ITSAbsoluteDelay> Delay(this ISADelay<ITSAbsoluteDelay> delay, DateTime date)
        {
            SelectiveAccept s = ((SASyntaxBase)delay).Select;

            Timeout timeout = new Timeout(date) { Barrier = s.CurrentSimpleBarrier };

            if (timeout.IsOpened() && s.Timeout.IsLater(timeout))
                s.Timeout = timeout;

            s.CurrentContinuable = timeout;

            return new SAAfterDelay<ITSAbsoluteDelay> { Select = s };
        }

        #endregion


        #region Implementation of ISABeforeThen

        /// <summary>
        /// Add continuation statements.
        /// </summary>
        /// <typeparam name="T">The type returned</typeparam>
        /// <param name="iba">The current instance</param>
        /// <param name="continuation">The continuation statements.</param>
        /// <returns></returns>
        public static T Then<T>(this ISABeforeThen<T> iba, Action continuation)
            where T : SASyntaxBase, new()
        {
            SelectiveAccept s = ((SASyntaxBase)iba).Select;

            s.CurrentContinuable.Continuation = continuation;

            return new T { Select = s };
        }

        #endregion


        #region Implementation of ISABeforeWhen<T>

        /// <summary>
        /// Add a simple barrier.
        /// </summary>
        /// <typeparam name="T">The return type</typeparam>
        /// <param name="ibw">The current instance</param>
        /// <param name="barrier">The barrier.</param>
        /// <returns></returns>
        public static T When<T>(this ISABeforeWhen<T> ibw, Func<bool> barrier)
            where T : SASyntaxBase, new()
        {
            SelectiveAccept s = ((SASyntaxBase)ibw).Select;

            //if (barrier == null)
            //{
            //    s.Task.OnSelectSyntaxError();
            //    throw Errors.BarrierIsNull();
            //}

            s.CurrentSimpleBarrier = barrier;

            return new T { Select = s };
        }

        #endregion


        #region Implementation of ISABeforeIndexedWhen<T, IndexT>

        /// <summary>
        /// Add an indexed barrier.
        /// </summary>
        /// <typeparam name="IndexT">The type of the index.</typeparam>
        /// <typeparam name="T">The return type</typeparam>
        /// <param name="ibiw">The current instance</param>
        /// <param name="indexedBarrier">The indexed barrier.</param>
        /// <returns></returns>
        public static SABeforeAccept<IndexT, T> When<IndexT, T>(this ISABeforeIndexedWhen<T> ibiw, Func<IndexT, bool> indexedBarrier)
            where T : SASyntaxBase, new()
        {
            SelectiveAccept s = ((SASyntaxBase)ibiw).Select;

            //if (indexedBarrier == null)
            //{
            //    s.Task.OnSelectSyntaxError();
            //    throw Errors.BarrierIsNull();
            //}

            s.SetCurrentIndexedBarrier(indexedBarrier);

            return new SABeforeAccept<IndexT, T> { Select = s };
        }

        #endregion


        #region Implementation of ITSBeforeElse

        /// <summary>
        /// Add an else alternative.
        /// </summary>
        /// <param name="ibe">The current instance</param>
        /// <param name="elseAlternative">The else alternative.</param>
        /// <returns></returns>
        public static SAAfterElse Else(this ISABeforeElse ibe, Action elseAlternative)
        {
            SelectiveAccept s = ((SASyntaxBase)ibe).Select;

            if (elseAlternative == null)
                s.Else = () => { };
            else
                s.Else = elseAlternative;

            return new SAAfterElse { Select = s };
        }

        #endregion


        #region Helper methods for ITSBEforeAccept implementation

        // TODO: comment all the following methods
        private static ExecutionContext AcceptAny<ExecuteDelegateT>(SelectiveAccept s, IExecutable executable, ExecuteDelegateT body, bool checkBody, Func<Exception, bool> exceptionHandler)
            where ExecuteDelegateT : class
        {
            // Check that the select is not within the abortable part of a selective call
            if (ThreadWrapper.CurrentThread.InAbortablePart)
                throw Errors.AcceptNotAllowedInAbortablePart(Task.CurrentTask);

            if (checkBody && body == null)
                throw Errors.BodyIsNull(executable);

            // ReSharper disable PossibleNullReferenceException
            if (body != null && (body as MulticastDelegate).Target as IExecutable != null)
                throw Errors.AcceptBodyIsSynchronized(s.Task, (body as MulticastDelegate).Target as SynchronizedMethod);
            // ReSharper restore PossibleNullReferenceException

            if (executable.Family.CurrentlyBeingAccepted)
                throw Errors.InvalidNestedAccept(s.Task, executable.Family);

            if (executable.Family.Owner != s.Task)
                throw Errors.AcceptCallNotOwned(executable.Family);

            ExecutionContext context = executable.CreateContext();
            context.ExceptionHandler = exceptionHandler;
            context.Barrier = s.CurrentSimpleBarrier;

            s.CurrentContinuable = context;

            if (!context.IsClosed)
            {
                s.OpenEntries += 1;
                context.Target.AcceptableCalls.Add(context);
            }

            if (body != null)
                ((ExecutionContext<ExecuteDelegateT>)context).Body = body;

            return context;
        }


        internal static ExecutionContext AcceptEntry<CallDelegateT>(SelectiveAccept s, CallDelegateT call, CallDelegateT body, bool checkBody, Func<Exception, bool> exceptionHandler)
            where CallDelegateT : class
        {
            if (call == null)
                throw Errors.EntryIsNull();

            // ReSharper disable PossibleNullReferenceException
            var executable = (call as MulticastDelegate).Target as IExecutable;
            // ReSharper restore PossibleNullReferenceException

            if (executable == null)
                // ReSharper disable PossibleNullReferenceException
                throw Errors.AcceptCallNotSynchronized(s.Task, (call as MulticastDelegate).Target);
            // ReSharper restore PossibleNullReferenceException

            return AcceptAny(s, executable, body, checkBody, exceptionHandler);
        }


        private static T AcceptEntry<T, CallDelegateT>(SelectiveAccept s, CallDelegateT call, CallDelegateT body, bool checkBody, Func<Exception, bool> exceptionHandler)
            where T : SASyntaxBase, new()
            where CallDelegateT : class
        {
            AcceptEntry(s, call, body, checkBody, exceptionHandler);
            return new T { Select = s };
        }


        internal static ExecutionContext AcceptFamily<IndexT, ExecuteDelegateT>(SelectiveAccept s, IExecutable family, ExecuteDelegateT body, bool checkBody, Func<Exception, bool> exceptionHandler)
            where ExecuteDelegateT : class
        {
            if (family == null)
                throw Errors.EntryIsNull();

            ExecutionContext context = AcceptAny(s, family, body, checkBody, exceptionHandler);

            ((IGuardable<IndexT>)context).IndexedBarrier = s.GetCurrentIndexedBarrier<IndexT>();

            return context;
        }


        private static T AcceptFamily<T, IndexT, ExecuteDelegateT>(SelectiveAccept s, IExecutable family, ExecuteDelegateT body, bool checkBody, Func<Exception, bool> exceptionHandler)
            where T : SASyntaxBase, new()
            where ExecuteDelegateT : class
        {
            AcceptFamily<IndexT, ExecuteDelegateT>(s, family, body, checkBody, exceptionHandler);
            return new T { Select = s };
        }


        internal static ExecutionContext AcceptMember<IndexT, CallDelegateT, ExecuteDelegateT>(SelectiveAccept s, CallDelegateT call, ExecuteDelegateT body, bool checkBody, Func<Exception, bool> exceptionHandler)
            where CallDelegateT : class
            where ExecuteDelegateT : class
        {
            if (call == null)
                throw Errors.EntryIsNull();

            // ReSharper disable PossibleNullReferenceException
            var executable1 = (call as MulticastDelegate).Target as IExecutable;
            // ReSharper restore PossibleNullReferenceException

            // Check that the provided entry is an executable entity (entry or entry family member)
            if (executable1 == null)
                // ReSharper disable PossibleNullReferenceException
                throw Errors.AcceptCallNotSynchronized(s.Task, (call as MulticastDelegate).Target);
            // ReSharper restore PossibleNullReferenceException

            // ReSharper disable PossibleNullReferenceException
            var executable2 = (call as MulticastDelegate).Target as IExecutable<ExecuteDelegateT>;
            // ReSharper restore PossibleNullReferenceException

            // Check that the provided entry is an executable entity with correct body profile
            if (executable2 == null)
                throw Errors.IndexTypeMismatch(s.Task, executable1.Family);

            ExecutionContext execute = AcceptAny(s, executable1, body, checkBody, exceptionHandler);

            ((IGuardable<IndexT>)execute).IndexedBarrier = s.GetCurrentIndexedBarrier<IndexT>();

            return execute;
        }


        private static T AcceptMember<T, IndexT, CallDelegateT, ExecuteDelegateT>(SelectiveAccept s, CallDelegateT call, ExecuteDelegateT body, bool checkBody, Func<Exception, bool> exceptionHandler)
            where T : SASyntaxBase, new()
            where CallDelegateT : class
            where ExecuteDelegateT : class
        {
            AcceptMember<IndexT, CallDelegateT, ExecuteDelegateT>(s, call, body, checkBody, exceptionHandler);
            return new T { Select = s };
        }

        #endregion


        #region EXTENSION POINTS

        #region For entry/entry family with 0 parameters

        /// <summary>
        /// Add an accept alternative.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="iba">The current instance</param>
        /// <param name="entry">The accepted entry.</param>
        /// <param name="Do">The accept body.</param>
        /// <param name="Exception">The accept body's exception handler.</param>
        /// <returns></returns>
        public static T Accept<T>(this ISABeforeAccept<T> iba, Action entry, Action Do = null, Func<Exception, bool> Exception = null)
            where T : SASyntaxBase, new()
        {
            return AcceptEntry<T, Action>(((SASyntaxBase)iba).Select, entry, Do, false, Exception);
        }


        /// <summary>
        /// Add an accept alternative.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="RetT">The result type</typeparam>
        /// <param name="iba">The current instance</param>
        /// <param name="entry">The accepted entry.</param>
        /// <param name="Do">The accept body.</param>
        /// <param name="Exception">The accept body's exception handler.</param>
        /// <returns></returns>
        public static T Accept<T, RetT>(this ISABeforeAccept<T> iba, Func<RetT> entry, Func<RetT> Do, Func<Exception, bool> Exception = null)
            where T : SASyntaxBase, new()
        {
            return AcceptEntry<T, Func<RetT>>(((SASyntaxBase)iba).Select, entry, Do, true, Exception);
        }


        /// <summary>
        /// Add an accept alternative.
        /// </summary>
        /// <typeparam name="T">The entry family index type</typeparam>
        /// <typeparam name="IndexT"></typeparam>
        /// <param name="iba">The current instance</param>
        /// <param name="entry">The accepted entry family member.</param>
        /// <param name="Do">The accept body.</param>
        /// <param name="Exception">The accept body's exception handler.</param>
        /// <returns></returns>
        public static T Accept<T, IndexT>(this ISABeforeAccept<T> iba, Action entry, Action<IndexT> Do = null, Func<Exception, bool> Exception = null)
            where T : SASyntaxBase, new()
        {
            return AcceptMember<T, IndexT, Action, Action<IndexT>>(((SASyntaxBase)iba).Select, entry, Do, false, Exception);
        }


        /// <summary>
        /// Add an accept alternative.
        /// </summary>
        /// <typeparam name="T">The entry family index type</typeparam>
        /// <typeparam name="IndexT"></typeparam>
        /// <typeparam name="RetT">The result type</typeparam>
        /// <param name="iba">The current instance</param>
        /// <param name="entry">The accepted entry family member.</param>
        /// <param name="Do">The accept body.</param>
        /// <param name="Exception">The accept body's exception handler.</param>
        /// <returns></returns>
        public static T Accept<T, IndexT, RetT>(this ISABeforeAccept<T> iba, Func<RetT> entry, Func<IndexT, RetT> Do, Func<Exception, bool> Exception = null)
            where T : SASyntaxBase, new()
        {
            return AcceptMember<T, IndexT, Func<RetT>, Func<IndexT, RetT>>(((SASyntaxBase)iba).Select, entry, Do, true, Exception);
        }


        /// <summary>
        /// Add an accept alternative.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="IndexT">The entry family index type</typeparam>
        /// <param name="iba">The current instance</param>
        /// <param name="family">The accepted entry family.</param>
        /// <param name="Do">The accept body.</param>
        /// <param name="Exception">The accept body's exception handler.</param>
        /// <returns></returns>
        public static T Accept<T, IndexT>(this ISABeforeAccept<T> iba, ActionFamily<IndexT> family, Action<IndexT> Do = null, Func<Exception, bool> Exception = null)
            where T : SASyntaxBase, new()
        {
            return AcceptFamily<T, IndexT, Action<IndexT>>(((SASyntaxBase)iba).Select, family, Do, false, Exception);
        }


        /// <summary>
        /// Add an accept alternative.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="IndexT">The entry family index type</typeparam>
        /// <typeparam name="RetT">The result type</typeparam>
        /// <param name="iba">The current instance</param>
        /// <param name="family">The accepted entry family.</param>
        /// <param name="Do">The accept body.</param>
        /// <param name="Exception">The accept body's exception handler.</param>
        /// <returns></returns>
        public static T Accept<T, IndexT, RetT>(this ISABeforeAccept<T> iba, FuncFamily<IndexT, RetT> family, Func<IndexT, RetT> Do, Func<Exception, bool> Exception = null)
            where T : SASyntaxBase, new()
        {
            return AcceptFamily<T, IndexT, Func<IndexT, RetT>>(((SASyntaxBase)iba).Select, family, Do, true, Exception);
        }


        /// <summary>
        /// Add an accept alternative.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="IndexT">The entry family index type</typeparam>
        /// <param name="iba">The current instance</param>
        /// <param name="family">The accepted entry family.</param>
        /// <param name="Do">The accept body.</param>
        /// <param name="Exception">The accept body's exception handler.</param>
        /// <returns></returns>
        public static T Accept<T, IndexT>(this ISABeforeAccept<T, IndexT> iba, ActionFamily<IndexT> family, Action<IndexT> Do = null, Func<Exception, bool> Exception = null)
            where T : SASyntaxBase, new()
        {
            return AcceptFamily<T, IndexT, Action<IndexT>>(((SASyntaxBase)iba).Select, family, Do, false, Exception);
        }


        /// <summary>
        /// Add an accept alternative.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="IndexT">The entry family index type</typeparam>
        /// <typeparam name="RetT">The result type</typeparam>
        /// <param name="iba">The current instance</param>
        /// <param name="family">The accepted entry family.</param>
        /// <param name="Do">The accept body.</param>
        /// <param name="Exception">The accept body's exception handler.</param>
        /// <returns></returns>
        public static T Accept<T, IndexT, RetT>(this ISABeforeAccept<T, IndexT> iba, FuncFamily<IndexT, RetT> family, Func<IndexT, RetT> Do, Func<Exception, bool> Exception = null)
            where T : SASyntaxBase, new()
        {
            return AcceptFamily<T, IndexT, Func<IndexT, RetT>>(((SASyntaxBase)iba).Select, family, Do, true, Exception);
        }

        #endregion


        #region For entry/entry family with 1 parameters

        /// <summary>
        /// Add an accept alternative.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="P1T">The type of the 1st parameter</typeparam>
        /// <param name="iba">The current instance</param>
        /// <param name="entry">The accepted entry.</param>
        /// <param name="Do">The accept body.</param>
        /// <param name="Exception">The accept body's exception handler.</param>
        /// <returns></returns>
        public static T Accept<T, P1T>(this ISABeforeAccept<T> iba, Action<P1T> entry, Action<P1T> Do = null, Func<Exception, bool> Exception = null)
            where T : SASyntaxBase, new()
        {
            return AcceptEntry<T, Action<P1T>>(((SASyntaxBase)iba).Select, entry, Do, false, Exception);
        }


        /// <summary>
        /// Add an accept alternative.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="P1T">The type of the 1st parameter</typeparam>
        /// <typeparam name="RetT">The result type</typeparam>
        /// <param name="iba">The current instance</param>
        /// <param name="entry">The accepted entry.</param>
        /// <param name="Do">The accept body.</param>
        /// <param name="Exception">The accept body's exception handler.</param>
        /// <returns></returns>
        public static T Accept<T, P1T, RetT>(this ISABeforeAccept<T> iba, Func<P1T, RetT> entry, Func<P1T, RetT> Do, Func<Exception, bool> Exception = null)
            where T : SASyntaxBase, new()
        {
            return AcceptEntry<T, Func<P1T, RetT>>(((SASyntaxBase)iba).Select, entry, Do, true, Exception);
        }


        /// <summary>
        /// Add an accept alternative.
        /// </summary>
        /// <typeparam name="T">The entry family index type</typeparam>
        /// <typeparam name="IndexT"></typeparam>
        /// <typeparam name="P1T">The type of the 1st parameter</typeparam>
        /// <param name="iba">The current instance</param>
        /// <param name="entry">The accepted entry family member.</param>
        /// <param name="Do">The accept body.</param>
        /// <param name="Exception">The accept body's exception handler.</param>
        /// <returns></returns>
        public static T Accept<T, IndexT, P1T>(this ISABeforeAccept<T> iba, Action<P1T> entry, Action<IndexT, P1T> Do = null, Func<Exception, bool> Exception = null)
            where T : SASyntaxBase, new()
        {
            return AcceptMember<T, IndexT, Action<P1T>, Action<IndexT, P1T>>(((SASyntaxBase)iba).Select, entry, Do, false, Exception);
        }


        /// <summary>
        /// Add an accept alternative.
        /// </summary>
        /// <typeparam name="T">The entry family index type</typeparam>
        /// <typeparam name="IndexT"></typeparam>
        /// <typeparam name="P1T">The type of the 1st parameter</typeparam>
        /// <typeparam name="RetT">The result type</typeparam>
        /// <param name="iba">The current instance</param>
        /// <param name="entry">The accepted entry family member.</param>
        /// <param name="Do">The accept body.</param>
        /// <param name="Exception">The accept body's exception handler.</param>
        /// <returns></returns>
        public static T Accept<T, IndexT, P1T, RetT>(this ISABeforeAccept<T> iba, Func<P1T, RetT> entry, Func<IndexT, P1T, RetT> Do, Func<Exception, bool> Exception = null)
            where T : SASyntaxBase, new()
        {
            return AcceptMember<T, IndexT, Func<P1T, RetT>, Func<IndexT, P1T, RetT>>(((SASyntaxBase)iba).Select, entry, Do, true, Exception);
        }


        /// <summary>
        /// Add an accept alternative.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="IndexT">The entry family index type</typeparam>
        /// <typeparam name="P1T">The type of the 1st parameter</typeparam>
        /// <param name="iba">The current instance</param>
        /// <param name="family">The accepted entry family.</param>
        /// <param name="Do">The accept body.</param>
        /// <param name="Exception">The accept body's exception handler.</param>
        /// <returns></returns>
        public static T Accept<T, IndexT, P1T>(this ISABeforeAccept<T> iba, ActionFamily<IndexT, P1T> family, Action<IndexT, P1T> Do = null, Func<Exception, bool> Exception = null)
            where T : SASyntaxBase, new()
        {
            return AcceptFamily<T, IndexT, Action<IndexT, P1T>>(((SASyntaxBase)iba).Select, family, Do, false, Exception);
        }


        /// <summary>
        /// Add an accept alternative.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="IndexT">The entry family index type</typeparam>
        /// <typeparam name="P1T">The type of the 1st parameter</typeparam>
        /// <typeparam name="RetT">The result type</typeparam>
        /// <param name="iba">The current instance</param>
        /// <param name="family">The accepted entry family.</param>
        /// <param name="Do">The accept body.</param>
        /// <param name="Exception">The accept body's exception handler.</param>
        /// <returns></returns>
        public static T Accept<T, IndexT, P1T, RetT>(this ISABeforeAccept<T> iba, FuncFamily<IndexT, P1T, RetT> family, Func<IndexT, P1T, RetT> Do, Func<Exception, bool> Exception = null)
            where T : SASyntaxBase, new()
        {
            return AcceptFamily<T, IndexT, Func<IndexT, P1T, RetT>>(((SASyntaxBase)iba).Select, family, Do, true, Exception);
        }


        /// <summary>
        /// Add an accept alternative.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="IndexT">The entry family index type</typeparam>
        /// <typeparam name="P1T">The type of the 1st parameter</typeparam>
        /// <param name="iba">The current instance</param>
        /// <param name="family">The accepted entry family.</param>
        /// <param name="Do">The accept body.</param>
        /// <param name="Exception">The accept body's exception handler.</param>
        /// <returns></returns>
        public static T Accept<T, IndexT, P1T>(this ISABeforeAccept<T, IndexT> iba, ActionFamily<IndexT, P1T> family, Action<IndexT, P1T> Do = null, Func<Exception, bool> Exception = null)
            where T : SASyntaxBase, new()
        {
            return AcceptFamily<T, IndexT, Action<IndexT, P1T>>(((SASyntaxBase)iba).Select, family, Do, false, Exception);
        }


        /// <summary>
        /// Add an accept alternative.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="IndexT">The entry family index type</typeparam>
        /// <typeparam name="P1T">The type of the 1st parameter</typeparam>
        /// <typeparam name="RetT">The result type</typeparam>
        /// <param name="iba">The current instance</param>
        /// <param name="family">The accepted entry family.</param>
        /// <param name="Do">The accept body.</param>
        /// <param name="Exception">The accept body's exception handler.</param>
        /// <returns></returns>
        public static T Accept<T, IndexT, P1T, RetT>(this ISABeforeAccept<T, IndexT> iba, FuncFamily<IndexT, P1T, RetT> family, Func<IndexT, P1T, RetT> Do, Func<Exception, bool> Exception = null)
            where T : SASyntaxBase, new()
        {
            return AcceptFamily<T, IndexT, Func<IndexT, P1T, RetT>>(((SASyntaxBase)iba).Select, family, Do, true, Exception);
        }

        #endregion


        #region For entry/entry family with 2 parameters

        /// <summary>
        /// Add an accept alternative.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="P1T">The type of the 1st parameter</typeparam>
        /// <typeparam name="P2T">The type of the 1st parameter</typeparam>
        /// <param name="iba">The current instance</param>
        /// <param name="entry">The accepted entry.</param>
        /// <param name="Do">The accept body.</param>
        /// <param name="Exception">The accept body's exception handler.</param>
        /// <returns></returns>
        public static T Accept<T, P1T, P2T>(this ISABeforeAccept<T> iba, Action<P1T, P2T> entry, Action<P1T, P2T> Do = null, Func<Exception, bool> Exception = null)
            where T : SASyntaxBase, new()
        {
            return AcceptEntry<T, Action<P1T, P2T>>(((SASyntaxBase)iba).Select, entry, Do, false, Exception);
        }


        /// <summary>
        /// Add an accept alternative.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="P1T">The type of the 1st parameter</typeparam>
        /// <typeparam name="P2T">The type of the 1st parameter</typeparam>
        /// <typeparam name="RetT">The result type</typeparam>
        /// <param name="iba">The current instance</param>
        /// <param name="entry">The accepted entry.</param>
        /// <param name="Do">The accept body.</param>
        /// <param name="Exception">The accept body's exception handler.</param>
        /// <returns></returns>
        public static T Accept<T, P1T, P2T, RetT>(this ISABeforeAccept<T> iba, Func<P1T, P2T, RetT> entry, Func<P1T, P2T, RetT> Do, Func<Exception, bool> Exception = null)
            where T : SASyntaxBase, new()
        {
            return AcceptEntry<T, Func<P1T, P2T, RetT>>(((SASyntaxBase)iba).Select, entry, Do, true, Exception);
        }


        /// <summary>
        /// Add an accept alternative.
        /// </summary>
        /// <typeparam name="T">The entry family index type</typeparam>
        /// <typeparam name="IndexT"></typeparam>
        /// <typeparam name="P1T">The type of the 1st parameter</typeparam>
        /// <typeparam name="P2T">The type of the 1st parameter</typeparam>
        /// <param name="iba">The current instance</param>
        /// <param name="entry">The accepted entry family member.</param>
        /// <param name="Do">The accept body.</param>
        /// <param name="Exception">The accept body's exception handler.</param>
        /// <returns></returns>
        public static T Accept<T, IndexT, P1T, P2T>(this ISABeforeAccept<T> iba, Action<P1T, P2T> entry, Action<IndexT, P1T, P2T> Do = null, Func<Exception, bool> Exception = null)
            where T : SASyntaxBase, new()
        {
            return AcceptMember<T, IndexT, Action<P1T, P2T>, Action<IndexT, P1T, P2T>>(((SASyntaxBase)iba).Select, entry, Do, false, Exception);
        }


        /// <summary>
        /// Add an accept alternative.
        /// </summary>
        /// <typeparam name="T">The entry family index type</typeparam>
        /// <typeparam name="IndexT"></typeparam>
        /// <typeparam name="P1T">The type of the 1st parameter</typeparam>
        /// <typeparam name="P2T">The type of the 1st parameter</typeparam>
        /// <typeparam name="RetT">The result type</typeparam>
        /// <param name="iba">The current instance</param>
        /// <param name="entry">The accepted entry family member.</param>
        /// <param name="Do">The accept body.</param>
        /// <param name="Exception">The accept body's exception handler.</param>
        /// <returns></returns>
        public static T Accept<T, IndexT, P1T, P2T, RetT>(this ISABeforeAccept<T> iba, Func<P1T, P2T, RetT> entry, Func<IndexT, P1T, P2T, RetT> Do, Func<Exception, bool> Exception = null)
            where T : SASyntaxBase, new()
        {
            return AcceptMember<T, IndexT, Func<P1T, P2T, RetT>, Func<IndexT, P1T, P2T, RetT>>(((SASyntaxBase)iba).Select, entry, Do, true, Exception);
        }


        /// <summary>
        /// Add an accept alternative.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="IndexT">The entry family index type</typeparam>
        /// <typeparam name="P1T">The type of the 1st parameter</typeparam>
        /// <typeparam name="P2T">The type of the 1st parameter</typeparam>
        /// <param name="iba">The current instance</param>
        /// <param name="family">The accepted entry family.</param>
        /// <param name="Do">The accept body.</param>
        /// <param name="Exception">The accept body's exception handler.</param>
        /// <returns></returns>
        public static T Accept<T, IndexT, P1T, P2T>(this ISABeforeAccept<T> iba, ActionFamily<IndexT, P1T, P2T> family, Action<IndexT, P1T, P2T> Do = null, Func<Exception, bool> Exception = null)
            where T : SASyntaxBase, new()
        {
            return AcceptFamily<T, IndexT, Action<IndexT, P1T, P2T>>(((SASyntaxBase)iba).Select, family, Do, false, Exception);
        }


        /// <summary>
        /// Add an accept alternative.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="IndexT">The entry family index type</typeparam>
        /// <typeparam name="P1T">The type of the 1st parameter</typeparam>
        /// <typeparam name="P2T">The type of the 1st parameter</typeparam>
        /// <typeparam name="RetT">The result type</typeparam>
        /// <param name="iba">The current instance</param>
        /// <param name="family">The accepted entry family.</param>
        /// <param name="Do">The accept body.</param>
        /// <param name="Exception">The accept body's exception handler.</param>
        /// <returns></returns>
        public static T Accept<T, IndexT, P1T, P2T, RetT>(this ISABeforeAccept<T> iba, FuncFamily<IndexT, P1T, P2T, RetT> family, Func<IndexT, P1T, P2T, RetT> Do, Func<Exception, bool> Exception = null)
            where T : SASyntaxBase, new()
        {
            return AcceptFamily<T, IndexT, Func<IndexT, P1T, P2T, RetT>>(((SASyntaxBase)iba).Select, family, Do, true, Exception);
        }


        /// <summary>
        /// Add an accept alternative.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="IndexT">The entry family index type</typeparam>
        /// <typeparam name="P1T">The type of the 1st parameter</typeparam>
        /// <typeparam name="P2T">The type of the 1st parameter</typeparam>
        /// <param name="iba">The current instance</param>
        /// <param name="family">The accepted entry family.</param>
        /// <param name="Do">The accept body.</param>
        /// <param name="Exception">The accept body's exception handler.</param>
        /// <returns></returns>
        public static T Accept<T, IndexT, P1T, P2T>(this ISABeforeAccept<T, IndexT> iba, ActionFamily<IndexT, P1T, P2T> family, Action<IndexT, P1T, P2T> Do = null, Func<Exception, bool> Exception = null)
            where T : SASyntaxBase, new()
        {
            return AcceptFamily<T, IndexT, Action<IndexT, P1T, P2T>>(((SASyntaxBase)iba).Select, family, Do, false, Exception);
        }


        /// <summary>
        /// Add an accept alternative.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="IndexT">The entry family index type</typeparam>
        /// <typeparam name="P1T">The type of the 1st parameter</typeparam>
        /// <typeparam name="P2T">The type of the 1st parameter</typeparam>
        /// <typeparam name="RetT">The result type</typeparam>
        /// <param name="iba">The current instance</param>
        /// <param name="family">The accepted entry family.</param>
        /// <param name="Do">The accept body.</param>
        /// <param name="Exception">The accept body's exception handler.</param>
        /// <returns></returns>
        public static T Accept<T, IndexT, P1T, P2T, RetT>(this ISABeforeAccept<T, IndexT> iba, FuncFamily<IndexT, P1T, P2T, RetT> family, Func<IndexT, P1T, P2T, RetT> Do, Func<Exception, bool> Exception = null)
            where T : SASyntaxBase, new()
        {
            return AcceptFamily<T, IndexT, Func<IndexT, P1T, P2T, RetT>>(((SASyntaxBase)iba).Select, family, Do, true, Exception);
        }

        #endregion


        #region For entry/entry family with 3 parameters

        /// <summary>
        /// Add an accept alternative.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="P1T">The type of the 1st parameter</typeparam>
        /// <typeparam name="P2T">The type of the 1st parameter</typeparam>
        /// <typeparam name="P3T">The type of the 1st parameter</typeparam>
        /// <param name="iba">The current instance</param>
        /// <param name="entry">The accepted entry.</param>
        /// <param name="Do">The accept body.</param>
        /// <param name="Exception">The accept body's exception handler.</param>
        /// <returns></returns>
        public static T Accept<T, P1T, P2T, P3T>(this ISABeforeAccept<T> iba, Action<P1T, P2T, P3T> entry, Action<P1T, P2T, P3T> Do = null, Func<Exception, bool> Exception = null)
            where T : SASyntaxBase, new()
        {
            return AcceptEntry<T, Action<P1T, P2T, P3T>>(((SASyntaxBase)iba).Select, entry, Do, false, Exception);
        }


        /// <summary>
        /// Add an accept alternative.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="P1T">The type of the 1st parameter</typeparam>
        /// <typeparam name="P2T">The type of the 1st parameter</typeparam>
        /// <typeparam name="P3T">The type of the 1st parameter</typeparam>
        /// <typeparam name="RetT">The result type</typeparam>
        /// <param name="iba">The current instance</param>
        /// <param name="entry">The accepted entry.</param>
        /// <param name="Do">The accept body.</param>
        /// <param name="Exception">The accept body's exception handler.</param>
        /// <returns></returns>
        public static T Accept<T, P1T, P2T, P3T, RetT>(this ISABeforeAccept<T> iba, Func<P1T, P2T, P3T, RetT> entry, Func<P1T, P2T, P3T, RetT> Do, Func<Exception, bool> Exception = null)
            where T : SASyntaxBase, new()
        {
            return AcceptEntry<T, Func<P1T, P2T, P3T, RetT>>(((SASyntaxBase)iba).Select, entry, Do, true, Exception);
        }


        /// <summary>
        /// Add an accept alternative.
        /// </summary>
        /// <typeparam name="T">The entry family index type</typeparam>
        /// <typeparam name="IndexT"></typeparam>
        /// <typeparam name="P1T">The type of the 1st parameter</typeparam>
        /// <typeparam name="P2T">The type of the 1st parameter</typeparam>
        /// <typeparam name="P3T">The type of the 1st parameter</typeparam>
        /// <param name="iba">The current instance</param>
        /// <param name="entry">The accepted entry family member.</param>
        /// <param name="Do">The accept body.</param>
        /// <param name="Exception">The accept body's exception handler.</param>
        /// <returns></returns>
        public static T Accept<T, IndexT, P1T, P2T, P3T>(this ISABeforeAccept<T> iba, Action<P1T, P2T, P3T> entry, Action<IndexT, P1T, P2T, P3T> Do = null, Func<Exception, bool> Exception = null)
            where T : SASyntaxBase, new()
        {
            return AcceptMember<T, IndexT, Action<P1T, P2T, P3T>, Action<IndexT, P1T, P2T, P3T>>(((SASyntaxBase)iba).Select, entry, Do, false, Exception);
        }


        /// <summary>
        /// Add an accept alternative.
        /// </summary>
        /// <typeparam name="T">The entry family index type</typeparam>
        /// <typeparam name="IndexT"></typeparam>
        /// <typeparam name="P1T">The type of the 1st parameter</typeparam>
        /// <typeparam name="P2T">The type of the 1st parameter</typeparam>
        /// <typeparam name="P3T">The type of the 1st parameter</typeparam>
        /// <typeparam name="RetT">The result type</typeparam>
        /// <param name="iba">The current instance</param>
        /// <param name="entry">The accepted entry family member.</param>
        /// <param name="Do">The accept body.</param>
        /// <param name="Exception">The accept body's exception handler.</param>
        /// <returns></returns>
        public static T Accept<T, IndexT, P1T, P2T, P3T, RetT>(this ISABeforeAccept<T> iba, Func<P1T, P2T, P3T, RetT> entry, Func<IndexT, P1T, P2T, P3T, RetT> Do, Func<Exception, bool> Exception = null)
            where T : SASyntaxBase, new()
        {
            return AcceptMember<T, IndexT, Func<P1T, P2T, P3T, RetT>, Func<IndexT, P1T, P2T, P3T, RetT>>(((SASyntaxBase)iba).Select, entry, Do, true, Exception);
        }


        /// <summary>
        /// Add an accept alternative.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="IndexT">The entry family index type</typeparam>
        /// <typeparam name="P1T">The type of the 1st parameter</typeparam>
        /// <typeparam name="P2T">The type of the 1st parameter</typeparam>
        /// <typeparam name="P3T">The type of the 1st parameter</typeparam>
        /// <param name="iba">The current instance</param>
        /// <param name="family">The accepted entry family.</param>
        /// <param name="Do">The accept body.</param>
        /// <param name="Exception">The accept body's exception handler.</param>
        /// <returns></returns>
        public static T Accept<T, IndexT, P1T, P2T, P3T>(this ISABeforeAccept<T> iba, ActionFamily<IndexT, P1T, P2T, P3T> family, Action<IndexT, P1T, P2T, P3T> Do = null, Func<Exception, bool> Exception = null)
            where T : SASyntaxBase, new()
        {
            return AcceptFamily<T, IndexT, Action<IndexT, P1T, P2T, P3T>>(((SASyntaxBase)iba).Select, family, Do, false, Exception);
        }


        /// <summary>
        /// Add an accept alternative.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="IndexT">The entry family index type</typeparam>
        /// <typeparam name="P1T">The type of the 1st parameter</typeparam>
        /// <typeparam name="P2T">The type of the 1st parameter</typeparam>
        /// <typeparam name="P3T">The type of the 1st parameter</typeparam>
        /// <typeparam name="RetT">The result type</typeparam>
        /// <param name="iba">The current instance</param>
        /// <param name="family">The accepted entry family.</param>
        /// <param name="Do">The accept body.</param>
        /// <param name="Exception">The accept body's exception handler.</param>
        /// <returns></returns>
        public static T Accept<T, IndexT, P1T, P2T, P3T, RetT>(this ISABeforeAccept<T> iba, FuncFamily<IndexT, P1T, P2T, P3T, RetT> family, Func<IndexT, P1T, P2T, P3T, RetT> Do, Func<Exception, bool> Exception = null)
            where T : SASyntaxBase, new()
        {
            return AcceptFamily<T, IndexT, Func<IndexT, P1T, P2T, P3T, RetT>>(((SASyntaxBase)iba).Select, family, Do, true, Exception);
        }


        /// <summary>
        /// Add an accept alternative.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="IndexT">The entry family index type</typeparam>
        /// <typeparam name="P1T">The type of the 1st parameter</typeparam>
        /// <typeparam name="P2T">The type of the 1st parameter</typeparam>
        /// <typeparam name="P3T">The type of the 1st parameter</typeparam>
        /// <param name="iba">The current instance</param>
        /// <param name="family">The accepted entry family.</param>
        /// <param name="Do">The accept body.</param>
        /// <param name="Exception">The accept body's exception handler.</param>
        /// <returns></returns>
        public static T Accept<T, IndexT, P1T, P2T, P3T>(this ISABeforeAccept<T, IndexT> iba, ActionFamily<IndexT, P1T, P2T, P3T> family, Action<IndexT, P1T, P2T, P3T> Do = null, Func<Exception, bool> Exception = null)
            where T : SASyntaxBase, new()
        {
            return AcceptFamily<T, IndexT, Action<IndexT, P1T, P2T, P3T>>(((SASyntaxBase)iba).Select, family, Do, false, Exception);
        }


        /// <summary>
        /// Add an accept alternative.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="IndexT">The entry family index type</typeparam>
        /// <typeparam name="P1T">The type of the 1st parameter</typeparam>
        /// <typeparam name="P2T">The type of the 1st parameter</typeparam>
        /// <typeparam name="P3T">The type of the 1st parameter</typeparam>
        /// <typeparam name="RetT">The result type</typeparam>
        /// <param name="iba">The current instance</param>
        /// <param name="family">The accepted entry family.</param>
        /// <param name="Do">The accept body.</param>
        /// <param name="Exception">The accept body's exception handler.</param>
        /// <returns></returns>
        public static T Accept<T, IndexT, P1T, P2T, P3T, RetT>(this ISABeforeAccept<T, IndexT> iba, FuncFamily<IndexT, P1T, P2T, P3T, RetT> family, Func<IndexT, P1T, P2T, P3T, RetT> Do, Func<Exception, bool> Exception = null)
            where T : SASyntaxBase, new()
        {
            return AcceptFamily<T, IndexT, Func<IndexT, P1T, P2T, P3T, RetT>>(((SASyntaxBase)iba).Select, family, Do, true, Exception);
        }

        #endregion


        #region For entry/entry family with 4 parameters

        /// <summary>
        /// Add an accept alternative.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="P1T">The type of the 1st parameter</typeparam>
        /// <typeparam name="P2T">The type of the 1st parameter</typeparam>
        /// <typeparam name="P3T">The type of the 1st parameter</typeparam>
        /// <typeparam name="P4T">The type of the 1st parameter</typeparam>
        /// <param name="iba">The current instance</param>
        /// <param name="entry">The accepted entry.</param>
        /// <param name="Do">The accept body.</param>
        /// <param name="Exception">The accept body's exception handler.</param>
        /// <returns></returns>
        public static T Accept<T, P1T, P2T, P3T, P4T>(this ISABeforeAccept<T> iba, Action<P1T, P2T, P3T, P4T> entry, Action<P1T, P2T, P3T, P4T> Do = null, Func<Exception, bool> Exception = null)
            where T : SASyntaxBase, new()
        {
            return AcceptEntry<T, Action<P1T, P2T, P3T, P4T>>(((SASyntaxBase)iba).Select, entry, Do, false, Exception);
        }


        /// <summary>
        /// Add an accept alternative.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="P1T">The type of the 1st parameter</typeparam>
        /// <typeparam name="P2T">The type of the 1st parameter</typeparam>
        /// <typeparam name="P3T">The type of the 1st parameter</typeparam>
        /// <typeparam name="P4T">The type of the 1st parameter</typeparam>
        /// <typeparam name="RetT">The result type</typeparam>
        /// <param name="iba">The current instance</param>
        /// <param name="entry">The accepted entry.</param>
        /// <param name="Do">The accept body.</param>
        /// <param name="Exception">The accept body's exception handler.</param>
        /// <returns></returns>
        public static T Accept<T, P1T, P2T, P3T, P4T, RetT>(this ISABeforeAccept<T> iba, Func<P1T, P2T, P3T, P4T, RetT> entry, Func<P1T, P2T, P3T, P4T, RetT> Do, Func<Exception, bool> Exception = null)
            where T : SASyntaxBase, new()
        {
            return AcceptEntry<T, Func<P1T, P2T, P3T, P4T, RetT>>(((SASyntaxBase)iba).Select, entry, Do, true, Exception);
        }


        /// <summary>
        /// Add an accept alternative.
        /// </summary>
        /// <typeparam name="T">The entry family index type</typeparam>
        /// <typeparam name="IndexT"></typeparam>
        /// <typeparam name="P1T">The type of the 1st parameter</typeparam>
        /// <typeparam name="P2T">The type of the 1st parameter</typeparam>
        /// <typeparam name="P3T">The type of the 1st parameter</typeparam>
        /// <typeparam name="P4T">The type of the 1st parameter</typeparam>
        /// <param name="iba">The current instance</param>
        /// <param name="entry">The accepted entry family member.</param>
        /// <param name="Do">The accept body.</param>
        /// <param name="Exception">The accept body's exception handler.</param>
        /// <returns></returns>
        public static T Accept<T, IndexT, P1T, P2T, P3T, P4T>(this ISABeforeAccept<T> iba, Action<P1T, P2T, P3T, P4T> entry, Action<IndexT, P1T, P2T, P3T, P4T> Do = null, Func<Exception, bool> Exception = null)
            where T : SASyntaxBase, new()
        {
            return AcceptMember<T, IndexT, Action<P1T, P2T, P3T, P4T>, Action<IndexT, P1T, P2T, P3T, P4T>>(((SASyntaxBase)iba).Select, entry, Do, false, Exception);
        }


        /// <summary>
        /// Add an accept alternative.
        /// </summary>
        /// <typeparam name="T">The entry family index type</typeparam>
        /// <typeparam name="IndexT"></typeparam>
        /// <typeparam name="P1T">The type of the 1st parameter</typeparam>
        /// <typeparam name="P2T">The type of the 1st parameter</typeparam>
        /// <typeparam name="P3T">The type of the 1st parameter</typeparam>
        /// <typeparam name="P4T">The type of the 1st parameter</typeparam>
        /// <typeparam name="RetT">The result type</typeparam>
        /// <param name="iba">The current instance</param>
        /// <param name="entry">The accepted entry family member.</param>
        /// <param name="Do">The accept body.</param>
        /// <param name="Exception">The accept body's exception handler.</param>
        /// <returns></returns>
        public static T Accept<T, IndexT, P1T, P2T, P3T, P4T, RetT>(this ISABeforeAccept<T> iba, Func<P1T, P2T, P3T, P4T, RetT> entry, Func<IndexT, P1T, P2T, P3T, P4T, RetT> Do, Func<Exception, bool> Exception = null)
            where T : SASyntaxBase, new()
        {
            return AcceptMember<T, IndexT, Func<P1T, P2T, P3T, P4T, RetT>, Func<IndexT, P1T, P2T, P3T, P4T, RetT>>(((SASyntaxBase)iba).Select, entry, Do, true, Exception);
        }


        /// <summary>
        /// Add an accept alternative.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="IndexT">The entry family index type</typeparam>
        /// <typeparam name="P1T">The type of the 1st parameter</typeparam>
        /// <typeparam name="P2T">The type of the 1st parameter</typeparam>
        /// <typeparam name="P3T">The type of the 1st parameter</typeparam>
        /// <typeparam name="P4T">The type of the 1st parameter</typeparam>
        /// <param name="iba">The current instance</param>
        /// <param name="family">The accepted entry family.</param>
        /// <param name="Do">The accept body.</param>
        /// <param name="Exception">The accept body's exception handler.</param>
        /// <returns></returns>
        public static T Accept<T, IndexT, P1T, P2T, P3T, P4T>(this ISABeforeAccept<T> iba, ActionFamily<IndexT, P1T, P2T, P3T, P4T> family, Action<IndexT, P1T, P2T, P3T, P4T> Do = null, Func<Exception, bool> Exception = null)
            where T : SASyntaxBase, new()
        {
            return AcceptFamily<T, IndexT, Action<IndexT, P1T, P2T, P3T, P4T>>(((SASyntaxBase)iba).Select, family, Do, false, Exception);
        }


        /// <summary>
        /// Add an accept alternative.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="IndexT">The entry family index type</typeparam>
        /// <typeparam name="P1T">The type of the 1st parameter</typeparam>
        /// <typeparam name="P2T">The type of the 1st parameter</typeparam>
        /// <typeparam name="P3T">The type of the 1st parameter</typeparam>
        /// <typeparam name="P4T">The type of the 1st parameter</typeparam>
        /// <typeparam name="RetT">The result type</typeparam>
        /// <param name="iba">The current instance</param>
        /// <param name="family">The accepted entry family.</param>
        /// <param name="Do">The accept body.</param>
        /// <param name="Exception">The accept body's exception handler.</param>
        /// <returns></returns>
        public static T Accept<T, IndexT, P1T, P2T, P3T, P4T, RetT>(this ISABeforeAccept<T> iba, FuncFamily<IndexT, P1T, P2T, P3T, P4T, RetT> family, Func<IndexT, P1T, P2T, P3T, P4T, RetT> Do, Func<Exception, bool> Exception = null)
            where T : SASyntaxBase, new()
        {
            return AcceptFamily<T, IndexT, Func<IndexT, P1T, P2T, P3T, P4T, RetT>>(((SASyntaxBase)iba).Select, family, Do, true, Exception);
        }


        /// <summary>
        /// Add an accept alternative.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="IndexT">The entry family index type</typeparam>
        /// <typeparam name="P1T">The type of the 1st parameter</typeparam>
        /// <typeparam name="P2T">The type of the 1st parameter</typeparam>
        /// <typeparam name="P3T">The type of the 1st parameter</typeparam>
        /// <typeparam name="P4T">The type of the 1st parameter</typeparam>
        /// <param name="iba">The current instance</param>
        /// <param name="family">The accepted entry family.</param>
        /// <param name="Do">The accept body.</param>
        /// <param name="Exception">The accept body's exception handler.</param>
        /// <returns></returns>
        public static T Accept<T, IndexT, P1T, P2T, P3T, P4T>(this ISABeforeAccept<T, IndexT> iba, ActionFamily<IndexT, P1T, P2T, P3T, P4T> family, Action<IndexT, P1T, P2T, P3T, P4T> Do = null, Func<Exception, bool> Exception = null)
            where T : SASyntaxBase, new()
        {
            return AcceptFamily<T, IndexT, Action<IndexT, P1T, P2T, P3T, P4T>>(((SASyntaxBase)iba).Select, family, Do, false, Exception);
        }


        /// <summary>
        /// Add an accept alternative.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="IndexT">The entry family index type</typeparam>
        /// <typeparam name="P1T">The type of the 1st parameter</typeparam>
        /// <typeparam name="P2T">The type of the 1st parameter</typeparam>
        /// <typeparam name="P3T">The type of the 1st parameter</typeparam>
        /// <typeparam name="P4T">The type of the 1st parameter</typeparam>
        /// <typeparam name="RetT">The result type</typeparam>
        /// <param name="iba">The current instance</param>
        /// <param name="family">The accepted entry family.</param>
        /// <param name="Do">The accept body.</param>
        /// <param name="Exception">The accept body's exception handler.</param>
        /// <returns></returns>
        public static T Accept<T, IndexT, P1T, P2T, P3T, P4T, RetT>(this ISABeforeAccept<T, IndexT> iba, FuncFamily<IndexT, P1T, P2T, P3T, P4T, RetT> family, Func<IndexT, P1T, P2T, P3T, P4T, RetT> Do, Func<Exception, bool> Exception = null)
            where T : SASyntaxBase, new()
        {
            return AcceptFamily<T, IndexT, Func<IndexT, P1T, P2T, P3T, P4T, RetT>>(((SASyntaxBase)iba).Select, family, Do, true, Exception);
        }

        #endregion

        #endregion

    }

}
